/**
 * 参考乾坤 scoped-css实现
 * https://gitee.com/scottcoder/qiankun/blob/v2.5.1/src/sandbox/patchers/css.ts
 * @author xiufu.wang
 */
function arrayify(list) {
    return [].slice.call(list, 0);
}

class ScopeCss {
    constructor(scopePrefix, styleElement) {
        this.prefix = scopePrefix
        this.styleElement = styleElement
        this.sheet = styleElement.sheet;
        this.sheet.disabled = true;
    }

    process() {
        if (!this.styleElement.textContent) {
            return null
        }
        const sheet = this.styleElement.sheet
        const rules = arrayify(sheet.cssRules || []);
        return this.rewrite(rules);
    }

    rewrite(rules) {
        let css = '';
        rules.forEach((rule) => {
            switch (rule.type) {
                case 1:
                    css += this.ruleStyle(rule);
                    break;
                case 4:
                    css += this.ruleMedia(rule);
                    break;
                case 12:
                    css += this.ruleSupport(rule);
                    break;
                default:
                    css += `${rule.cssText}`;
                    break;
            }
        });

        return css;
    }
    ruleStyle(rule) {
        const prefix = this.prefix
        const rootSelectorRE = /((?:[^\w\-.#]|^)(body|html|:root))/gm;
        const rootCombinationRE = /(html[^\w{[]+)/gm;

        const selector = rule.selectorText.trim();

        let { cssText } = rule;

        if (selector === 'html' || selector === 'body' || selector === ':root') {
            return cssText.replace(rootSelectorRE, prefix);
        }

        if (rootCombinationRE.test(rule.selectorText)) {
            const siblingSelectorRE = /(html[^\w{]+)(\+|~)/gm;
            if (!siblingSelectorRE.test(rule.selectorText)) {
                cssText = cssText.replace(rootCombinationRE, '');
            }
        }

        cssText = cssText.replace(/^[\s\S]+{/, (selectors) =>
            selectors.replace(/(^|,\n?)([^,]+)/g, (item, p, s) => {
                if (rootSelectorRE.test(item)) {
                    return item.replace(rootSelectorRE, (m) => {
                        const whitePrevChars = [',', '('];
                        if (m && whitePrevChars.includes(m[0])) {
                            return `${m[0]}${prefix}`;
                        }
                        return prefix;
                    });
                }

                return `${p}${prefix} ${s.replace(/^ */, '')}`;
            }),
        );

        return cssText;
    }
    ruleMedia(rule) {
        const css = this.rewrite(arrayify(rule.cssRules));
        return `@media ${rule.conditionText || rule.media.mediaText} {${css}}`;
    }
    ruleSupport(rule) {
        const css = this.rewrite(arrayify(rule.cssRules));
        return `@supports ${rule.conditionText || rule.cssText.split('{')[0]} {${css}}`;
    }
}

export default function (scopePrefix, styleElement) {
    const processor = new ScopeCss(scopePrefix, styleElement)
    return processor.process()
}
